(function(){

    var $ = function(id) {
        return id ? document.getElementById(id) : null;
    };

    // global
    var currentThreshold = 128,
        scale = 0.25,
        currentImage = '';

    var thresholdLevel = $('threshold-level'),
        thresholdVal = document.querySelector('.threshold-val'),
        mode = document.getElementsByName('mode'),
        add = $('add'),
        subtract = $('subtract'),
        scaleRatio = $('scale'),
        isThresholdOn = $('threshold-on'),
        modePanel = $('mode-panel'),
        modeBlack = $('mode-black'),
        modeColor = $('mode-color'),
        uploadBtn = $('img-upload'),
        createMapBtn=$("createMapBtn"),
        findPoint=$("findPoint"),
        prompt=$("prompt"),
        downloadBtn = $('download');
    var Things2=[]
    var row,col;
    /**
     * [thresholdConvert 阈值处理]
     * @param  {[type]} ctx       [description]
     * @param  {[type]} imageData [description]
     * @param  {[type]} threshold [阈值]
     * @param  {[type]} mode      [模式：0：彩色，1：黑白]
     * @return {[type]}           [description]
     */
    var thresholdConvert = function(ctx, imageData, threshold, mode,imgw,imgh) {
        var data = imageData.data;
        var Things=[]
        row=imgw
        col=imgh
        for (var i = 0; i < data.length; i += 4) {
            var red = data[i];
            var green = data[i + 1];
            var blue = data[i + 2];
            var alpha = data[i + 3];
            var toa

            // 灰度计算公式
            var gray = 0.299 * data[i] + 0.587 * data[i + 1] + 0.114 *data[i + 2];

            var color = gray >= threshold ? 255 : 0;

            data[i]     = (mode == 0 && color == 0) ? red : color;    // red
            data[i + 1] = (mode == 0 && color == 0) ? green : color;  // green
            data[i + 2] = (mode == 0 && color == 0) ? blue : color;   // blue
            data[i + 3] = alpha >= threshold ? 255 : 0;               // 去掉透明
            toa=data[i + 3]==255 ? 3:0
            Things.push(toa)
        }
       // console.log(imgw+":"+imgh)
       for(var j=0,len=Things.length;j<len;j+=imgw){
           Things2.push(Things.slice(j,j+imgw));
        }
       
        
        ctx.putImageData(imageData, 0, 0);
    };

    var render = function() {

        if (!currentImage) {
            alert('请先上传图片');
            return;
        }

        var canvasTemp = document.createElement('canvas');
        var context = canvasTemp.getContext('2d');

        var image = new Image();
        image.src = currentImage;
        image.onload = function() {
            canvasTemp.width = image.width * scale;
            canvasTemp.height = image.height * scale;
            // 缩小到 25%
            context.drawImage(image, 0, 0, image.width * scale, image.height * scale);

            var imageData = context.getImageData(0, 0, image.width * scale, image.height * scale);
            // 阈值处理
            isThresholdOn.checked && thresholdConvert(context, imageData, currentThreshold, getModeValue(mode),canvasTemp.width,canvasTemp.height);

            var dataURL = canvasTemp.toDataURL();
            var canvas = $('canvas');
            var ctx = canvas.getContext('2d');
            var img = new Image();
            img.src = dataURL;
            img.onload = function() {
                canvas.width = img.width / scale;
                canvas.height = img.height / scale;
                
                // 反锯齿
                ctx.imageSmoothingEnabled = false;
                ctx.mozImageSmoothingEnabled = false;
                ctx.webkitImageSmoothingEnabled = false;
                ctx.msImageSmoothingEnabled = false;

                ctx.drawImage(img, 0, 0, img.width / scale, img.height / scale);

                download();
            };
        };
    };

    var toggleThreshold = function(checked) {
        var thresholdRange = $('threshold-range');
        if (checked) {
            thresholdLevel.disabled = false;
            add.disabled = false;
            subtract.disabled = false;
            modeBlack.disabled = false;
            modeColor.disabled = false;
            thresholdRange.classList.remove('disable');
            modePanel.classList.remove('disable');
        } else {
            thresholdLevel.disabled = true;
            add.disabled = true;
            subtract.disabled = true;
            modeBlack.disabled = true;
            modeColor.disabled = true;
            thresholdRange.classList.add('disable');
            modePanel.classList.add('disable');
        }
    };

    var getModeValue = function(ele) {
        for (var i = 0, len = ele.length; i < len; i++) {
            if (ele[i].checked) {
                return ele[i].value;
            }
        }
    };


    var download = function() {
        downloadBtn.download = 'pixel.png';
        downloadBtn.href = canvas.toDataURL();
    };



    // events
    thresholdLevel.addEventListener('change', function() {
        currentThreshold = this.value;
        thresholdVal.innerHTML = currentThreshold;
        Things2=[]
        render();
    }, false);

    subtract.addEventListener('click', function() {
        currentThreshold = --thresholdLevel.value;
        thresholdVal.innerHTML = currentThreshold;
        Things2=[]
        render();
    }, false);

    add.addEventListener('click', function() {
        currentThreshold = ++thresholdLevel.value;
        thresholdVal.innerHTML = currentThreshold;
        Things2=[]
        render();
    }, false);

    scaleRatio.addEventListener('change', function() {
        scale = this.value;
        Things2=[]
        render();
    }, false);

    isThresholdOn.addEventListener('change', function() {
        toggleThreshold(this.checked);
        Things2=[]
        render();
    }, false);

    for (var i = 0, len = mode.length; i < len; i++) {
        mode[i].addEventListener('change', function() {
            render();
        }, false);
    }




    // upload
    uploadBtn.addEventListener('change', function(e) {

        var file = e.target.files[0];

        if (!file.type.match('image.*')) {
            return;
        }

        var reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = function(arg) {
            currentImage = arg.target.result;
            var img = '<img class="preview" src="' + arg.target.result + '" alt="preview" >';
            $('img-preview').innerHTML = img;

            render();
        };
    }, false);





function Point(){
           this.x=0;
           this.y=0;
           this.G=0;//G值 开始点 到当前点的移动量
           this.H=0;//H值　当前点移动目的地的移动量估算值
           this.father=null;
       };
       Point.prototype={
           Console:function(){
               console.log("x:"+this.x+" and y:"+this.y);
           },
           Init:function(x,y,father){
               this.x=x;
               this.y=y;
               this.father=father;
           }
       };
       function AStar(){
           //地图存放二维数组
           this.map=[];
           //行数
           this.rowCount=0;
           //列数
           this.colCount=0;
            //出发点
           this.startPoint=new Point();
           //终点
           this.endPoint=new Point();
           //存放Opint类的开放数组
           this.openList=[];
           //存在Opint类的关闭数组
           this.closeList=[];
          
       };
       AStar.prototype={
            //当前坐标是否在OpenList
           IsInOpenList:function(x,y){
                for(var i=0;i<this.openList.length;i++){
                    if(this.openList[i].x==x&&this.openList[i].y==y){
                        return true;
                    }
 
                }
               return false;
           },
           //当前坐标是否在CloseList
           IsInCloseList:function(x,y){
               for(var i=0;i<this.closeList.length;i++){
                   if(this.closeList[i].x==x&&this.closeList[i].y==y){
                       return true;
                   }
 
               }
               return false;
           },
           //是否为障碍物
           IsBar:function(x,y){
               if(this.map[x][y]==3){
                   console.log("bar...");
                   return true;
               }
               else{
                   console.log("no bar...")
                   return false;
               }
           },
           //计算G值;(p是Point类)
           GetG:function(p){
               if(p.father==null){
                   return 0;
               }
               return p.father.G+1;
           },
           //计算H值
           GetH:function(p,pb){
               return Math.abs(p.x-pb.x)+Math.abs(p.y-pb.y);
           },
           //添加当前点的上下左右相邻的方格到Open列表中
           AddNeiToOpenList:function(curPoint){
               for(var x=curPoint.x-1;x<=curPoint.x+1;x++){
                    for(var y=curPoint.y-1;y<=curPoint.y+1;y++){
                        //排除自身以及超出下标的点
                        if((x>=0&&x<this.colCount&&y>=0&&y<this.rowCount)&&!(curPoint.x==x&&curPoint.y==y)){
                            //排除斜对角
                            if(Math.abs(x-curPoint.x)+Math.abs(y-curPoint.y)==1){
                                //不是障碍物且不在关闭列表中
                                if(this.IsBar(x,y)==false&&this.IsInCloseList(x,y)==false){
                                    //不存在Open列表
                                    if(this.IsInOpenList(x,y)==false){
                                        var point=new Point();
                                        point.x=x;
                                        point.y=y;
                                        point.father=curPoint;
                                        point.G=this.GetG(point);
                                        point.H=this.GetH(point,this.endPoint);
                                        this.openList.push(point);
                                    }
                                }
                            }
                        }
                    }
               }
           },
           //在openlist集合中获取G+H为最小的Point点
           GetMinFFromOpenList:function(){
               var minPoint=null;
               var index=0;
               for(var i=0;i<this.openList.length;i++){
                   if(minPoint==null||minPoint.G+minPoint.H>=this.openList[i].G+this.openList[i].H){
                       minPoint=this.openList[i];
                       index=i;
                   }
               }
               return{
                   minPoint:minPoint,
                   index:index
               }
           },
           GetPointFromOpenList:function(x,y){
               for(var i=0;i<this.openList.length;i++){
                   if(this.openList[i].x==x&&this.openList[i].y==y){
                       return this.openList[i];
                   }
               }
               return null;
 
           },
            //开始寻找节点
            FindPoint:function(){
               this.openList.push(this.startPoint);
               console.log(this);
               while(this.IsInOpenList(this.endPoint.x,this.endPoint.y)==false||this.openList.length==0){
                    var curPoint=this.GetMinFFromOpenList().minPoint;
                   var index=this.GetMinFFromOpenList().index;
                   console.log("curPoint:"+index);
                   if(curPoint==null){
                       console.log("没有路");
                       return;
                   }
                   this.openList.splice(index,1);
                   this.closeList.push(curPoint);
                   this.AddNeiToOpenList(curPoint);
               }
               var p=this.GetPointFromOpenList(this.endPoint.x,this.endPoint.y);
               while(p.father!=null){
                   p= p.father;
                   console.log("father..");
                   this.map[p.x][p.y]=4;
               }
               this.map[this.endPoint.x][this.endPoint.y]=4;
               
            },
            PrintMap:function(){
 
            }
 
 
       };
       
       //地图类    map数组保存数字标识 :0 默认　1 开始点　2 结束点　3 障碍物
       function Map(id){
           this.map=[];
           this.container=document.getElementById(id);
           this.colCount=0;
           this.rowCount=0;
       }
       Map.prototype={
           init:function(colCount,rowCount){
               this.colCount=colCount;
               this.rowCount=rowCount;
               // for(var colIndex=0;colIndex<this.colCount;colIndex++){
               //     this.map.push([]);
               //     for(var rowIndex=0;rowIndex<this.rowCount;rowIndex++){
               //         this.map[colIndex].push(0);
               //     }
               // }
               this.map=Things2


           },
           drawMap:function(callback){
               for(var colIndex=0;colIndex<this.map.length;colIndex++){
                   for(var rowIndex=0;rowIndex<this.map[colIndex].length;rowIndex++){
                       var div=document.createElement("div");
                       div.style.top=colIndex*10+1+"px";
                       div.style.left=rowIndex*10+1+"px";
                       div.setAttribute("colIndex",colIndex);
                       div.setAttribute("rowIndex",rowIndex);
                       div.onclick=callback;
                       this.container.appendChild(div);
                   }
 
               }
               var divs=this.container.children;
               for(var i=0;i<divs.length;i++){
                   var colIndex=divs[i].getAttribute("colIndex");
                   var rowIndex=divs[i].getAttribute("rowIndex");
                   if(this.map[colIndex][rowIndex]==3){
                       divs[i].style.backgroundColor="black";
                   }
               }
 
           },
           drawPoints:function(){
               var divs=this.container.children;
               console.log(divs.length);
               console.log(this.map);
               var timer=1000;
               for(var i=0;i<divs.length;i++){
                   var colIndex=divs[i].getAttribute("colIndex");
                   var rowIndex=divs[i].getAttribute("rowIndex");
                   if(this.map[colIndex][rowIndex]==4){
                       divs[i].style.backgroundColor="red";
                   }
               }
           },
           getPoint:function(colIndex,rowIndex){
               return this.map[colIndex][rowIndex];
           },
           setStartPoint:function(colIndex,rowIndex){
               this.map[colIndex][rowIndex]=1;
           },
           setEndPoint:function(colIndex,rowIndex){
               this.map[colIndex][rowIndex]=2;
           },
           setBarPoint:function(colIndex,rowIndex){
               this.map[colIndex][rowIndex]=3;
               console.log(this.map)

           },
           clearMap:function(){
               this.map.splice(0,this.map.length);
               this.container.innerHTML="";
           }
 
       }
 
       
       
       var curMap=new Map("main");
       var state=0;//状态标识　0选择开始节点标识　1选择结束节点标识 2选择障碍物标识
       var aStar=new AStar();//寻路类
 
       createMapBtn.onclick=function(){
 
           curMap.clearMap();
           // console.log(Things2)
          
           curMap.init(col,row);
           aStar.map=curMap.map;
           aStar.colCount=col;
           aStar.rowCount=row;
           curMap.drawMap(function(){
                var colIndex=this.getAttribute("colIndex");
                var rowIndex=this.getAttribute("rowIndex");
                if(curMap.getPoint(colIndex,rowIndex)!=0){
                    return;
                }
                if(state==0){
                    this.style.backgroundColor="blue";
                    curMap.setStartPoint(colIndex,rowIndex);
                    aStar.startPoint.x=colIndex;
                    aStar.startPoint.y=rowIndex;
                    state=1;
                    prompt.innerHTML="请点击格子，设置终点";
 
                }else if(state==1){
                    this.style.backgroundColor="yellow";
                    curMap.setEndPoint(colIndex,rowIndex);
                    aStar.endPoint.x=colIndex;
                    aStar.endPoint.y=rowIndex;
                    prompt.innerHTML="请点击格子，设置障碍物";
                    console.log(findPoint);
                    findPoint.style.display="block";
                    state=2;
                }else if(state==2){

                    curMap.setBarPoint(colIndex,rowIndex);
                    this.style.backgroundColor="black";
                }
           });
           prompt.innerHTML="请点击格子，设置起始点";
       }
       findPoint.onclick=function(){
           // console.log(aStar.map);
           aStar.FindPoint();
           curMap.drawPoints()
       }

})();






